package gitobject;

import repository.Repository;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;

public class Blob extends GitObject{
	private Path path;
	private byte[] mode = null;
	private long last_time = 0;
	public Blob(){}
	public Blob(Path path){
		type = Type.Blob;
		mode = new byte[]{01,00,00,06,04,04};
		this.path = path;
		last_time = Repository.getInstance().getWorkTree()
				.resolve(this.path).toFile().lastModified();
		key = hashFile(Repository.getInstance().getWorkTree()
				.resolve(this.path).toFile()
		);
	}

	/**
	 *
	 * @return 返回Blob对象的路径
	 */
	public Path getPath(){return path;}

	/**
	 *
	 * @return 返回Blob对象最后一次修改时间
	 */
	public long getLastModified(){
		return last_time;
	}
	/**
	 * 对Blob类对象写入额外信息
	 * @param out
	 * @throws IOException
	 */

	@Override
	public void writeExtendInfo(DataOutputStream out) throws IOException {
		out.write(mode);
		out.writeLong(last_time);
		out.writeUTF(path.toString());
	}
	/**
	 * 从Blob类对象读取额外信息
	 * @param in
	 * @throws IOException
	 */

	@Override
	public void readExtendInfo(DataInputStream in) throws IOException {
		mode = in.readNBytes(6);
		last_time = in.readLong();
		path = Path.of(in.readUTF());
	}
	/**
	 * 为Blob类写入文件内容
	 * @param out
	 * @throws IOException
	 */

	@Override
	public void writeContent(DataOutputStream out) throws IOException {
		BufferedInputStream fin = new BufferedInputStream(new FileInputStream(
				Repository.getInstance().getWorkTree().resolve(path).toFile()
		));
		byte[] buffer = new byte[4096];
		int n;
		while ((n = fin.read(buffer)) > 0){
			out.write(buffer,0,n);
		}
	}
	/**
	 * 在目标路径下恢复Blob文件内容
	 * @param prefix 目标路径
	 * @throws IOException
	 */

	@Override
	public void restoreContent(Path prefix) throws IOException{
		File file = prefix.resolve(path).toFile();
		File parent = file.getParentFile();
		if(parent!= null){
			parent.mkdirs();
		}
		DataOutputStream out = new DataOutputStream(new FileOutputStream(file));
		DataInputStream in = new DataInputStream(new FileInputStream(getObjectPath().toFile()));
		in.skipBytes(in.readInt());

		byte[] buffer = new byte[4096];
		int n;
		while ((n = in.read(buffer)) > 0){
			out.write(buffer, 0, n);
		}
		in.close();
		out.close();
		file.setLastModified(last_time);
	}

	/**
	 * 获取Blob对象在仓库暂存区中的文件内容
	 * @return
	 * @throws IOException
	 */
	public List<String> getValue() throws IOException {
		DataInputStream in = new DataInputStream(new FileInputStream(getObjectPath().toFile()));
		int skip = in.readInt();
		in.skipBytes(skip);
		BufferedReader fread = new BufferedReader(new InputStreamReader(in));
		List<String> value = new ArrayList<>();
		String line = fread.readLine();
		while (line != null) {
			value.add(line);
			line = fread.readLine();
		}
		fread.close();
		return value;
	}
	/**
	 *
	 * @param file
	 * @return 计算文件的哈希值
	 */

	public static byte[] hashFile(File file){
		try {
			MessageDigest md = MessageDigest.getInstance("SHA-1");
			md.update(file.getName().getBytes(StandardCharsets.UTF_8));
			BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));
			int n;
			byte[] buffer = new byte[4096];
			while ((n = in.read(buffer)) > 0){
				md.update(buffer, 0, n);
			}
			return md.digest();
		} catch (NoSuchAlgorithmException | FileNotFoundException e) {
			throw new RuntimeException(e);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
}
